<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
		<title>js防抖和节流</title>
	</head>
	<body>
		1、函数防抖：是指在事件被触发 n 秒后再执行回调，如果在这 n 秒内事件又被触发，则重新计时。这可以使用在一些点击请求的事件上，避免因为用户的多次点击向后端发送多次请求。
		2、函数节流：是指规定一个单位时间，在这个单位时间内，只能有一次触发事件的回调函数执行，如果在同一个单位时间内某事件被触发多次，只有一次能生效。节流可以使用在 scroll
		函数的事件监听上，通过事件节流来降低事件调用的频率。
		3、简而言之：防抖就是在指定时间内高频率触发，只有在最后一次触发完毕后才会执行函数(点击一个按钮提交)，节流的话，这个触发动作不会停止，仅仅是在指定时间到后执行一次函数，说白了就是降低函数执行频率的(浏览器 滚动条事件)。
		<div id="app">
			<input id="input" placeholder="请输入...." />
		</div>

	</body>
	<script>
		/**
		 *防抖函数
		 * @param {Function} fun  需要防抖的函数
		 * @param {number} wait  延迟多少时间后执行
		 * @param {Boolean} immediate  wait指定时间内无论触发多少次，是否只有在首次触发，true是
		 * @returns {Function} Returns the new function.
		 */
		function debounce(fun, wait, immediate) {
			let timeout, result
			var debound = function() {
				var that = this
				var arg = arguments
				if (timeout) clearTimeout(timeout)

				var later = function() {
					timeout = null;
					if (!immediate) result = fun.apply(that, arg)
				}

				if (!timeout && immediate) {
					result = fun.apply(that, arg)
				}
				timeout = setTimeout(later, wait)
				return result
			}
			debound.cancle = function() {
				clearTimeout(timeout)
				timeout = null;
			}
			return debound
		}
		// 防抖函数简易版
		function debounce(fun, timeout = 300) {
			let timer=null;
			return () => {
				clearTimeout(timer)
				timer = setTimeout(() => {
					fn.apply(this,arguments);
					 timer=null
				}, timeout)
			}
		}

		let search = function() {
			console.log("搜素...",arguments)
		};
		input.addEventListener('keyup', debounce(search, 1000))




		// 函数节流的实现;
		function throttle(func, wait, options) {
			var timeout, context, args, result;
			var previous = 0;
			if (!options) options = {};

			var later = function() {
				previous = options.leading === false ? 0 : Date.now();
				timeout = null;
				result = func.apply(context, args);
			};

			var throttled = function() {
				var now = Date.now();
				if (!previous && options.leading === false) previous = now;
				var remaining = wait - (now - previous);
				context = this;
				args = arguments;
				if (remaining <= 0 || remaining > wait) {
					if (timeout) {
						clearTimeout(timeout);
						timeout = null;
					}
					previous = now;
					result = func.apply(context, args);
				} else if (!timeout && options.trailing !== false) {
					timeout = setTimeout(later, remaining);
				}
				return result;
			}
			throttled.cancel = function() {
				clearTimeout(timeout);
				previous = 0;
				timeout = context = args = null;
			};
			return throttled;
		}

		//函数节流的实现简易版 定时器方案
		function throttle(fn, wait) {
			var timer = null;
			return ()=> {
				if (!timer) {
					timer = setTimeout(()=> {
						fn.apply(this, arguments);
						timer = null;
					}, wait)
				}
			}
		}
		function handle() {
			console.log(Math.random());
		}
		window.addEventListener("mousemove", throttle(handle, 1000));
	</script>
</html>
